package com.miuugo.common.tools;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.*;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class WebUtils {
    private static final Logger logger = LoggerFactory.getLogger(WebUtils.class);
    public static final String INCLUDE_REQUEST_URI_ATTRIBUTE = "javax.servlet.include.request_uri";
    public static final String INCLUDE_CONTEXT_PATH_ATTRIBUTE = "javax.servlet.include.context_path";
    public static final String INCLUDE_SERVLET_PATH_ATTRIBUTE = "javax.servlet.include.servlet_path";
    public static final String INCLUDE_PATH_INFO_ATTRIBUTE = "javax.servlet.include.path_info";
    public static final String LAST_REQUEST_SESSION_KEY = "last_request_url";

    public WebUtils() {
    }

    public static String getRemoteAddr(HttpServletRequest request) {
        String ip = "";

        try {
            ip = request.getHeader("x-real-ip");
            if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("x-forwarded-for");
            }
            if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("Proxy-Client-IP");
            }

            if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("WL-Proxy-Client-IP");
            }

            if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_CLIENT_IP");
            }

            if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_X_FORWARDED_FOR");
            }

            if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getRemoteAddr();
            }

            String[] e = ip.split(",");
            if(e.length > 0) {
                ip = e[0];
            }
        } catch (Exception var3) {
            logger.warn(var3.getMessage());
        }

        return ip;
    }

    public static Map<String, String> getParameterMap(HttpServletRequest request) {
        Map properties = request.getParameterMap();
        HashMap returnMap = new HashMap();
        Iterator entries = properties.entrySet().iterator();
        String name = "";

        for(String value = ""; entries.hasNext(); returnMap.put(name, value)) {
            Entry entry = (Entry)entries.next();
            name = (String)entry.getKey();
            Object valueObj = entry.getValue();
            if(null == valueObj) {
                value = "";
            } else if(!(valueObj instanceof String[])) {
                value = valueObj.toString();
            } else {
                String[] values = (String[])((String[])valueObj);

                for(int i = 0; i < values.length; ++i) {
                    value = values[i] + ",";
                }

                value = value.substring(0, value.length() - 1);
            }
        }

        return returnMap;
    }

    public static Boolean getParameterMap(HttpServletRequest request, String str) {
        Boolean flag = Boolean.valueOf(true);
        Map propertiesMap = request.getParameterMap();
        if(propertiesMap.size() == 0) {
            flag = Boolean.valueOf(false);
        } else if(!propertiesMap.containsKey(str)) {
            flag = Boolean.valueOf(false);
        }

        return flag;
    }

    public static Boolean getParameterMap(HttpServletRequest request, String[] arr) {
        Boolean flag = Boolean.valueOf(true);
        Map propertiesMap = request.getParameterMap();
        if(propertiesMap.size() == 0) {
            flag = Boolean.valueOf(false);
        } else {
            for(int i = 0; i < arr.length; ++i) {
                if(!propertiesMap.containsKey(arr[i])) {
                    flag = Boolean.valueOf(false);
                }
            }
        }

        return flag;
    }

    public static Cookie getCookie(HttpServletRequest request, String name) {
        Cookie[] cookies = request.getCookies();
        if(cookies != null) {
            Cookie[] arr$ = cookies;
            int len$ = cookies.length;

            for(int i$ = 0; i$ < len$; ++i$) {
                Cookie cookie = arr$[i$];
                if(name.equals(cookie.getName())) {
                    return cookie;
                }
            }
        }

        return null;
    }

    public static boolean isCorsRequest(HttpServletRequest request) {
        return request.getHeader("Origin") != null;
    }

    public static boolean isCrossDomainFlightRequest(HttpServletRequest request) {
        return request.getHeader("Origin") != null && "OPTIONS".equalsIgnoreCase(request.getMethod()) && request.getHeader("Access-Control-Request-Method") != null;
    }

    public static void allowCrossDomian(HttpServletRequest request, HttpServletResponse response) {
        if(isCorsRequest(request)) {
            if(!response.containsHeader("Access-Control-Allow-Origin")) {
                String origin = request.getHeader("Origin");
                String allowMethod = null;
                String allowHeaders = null;
                if(isCrossDomainFlightRequest(request)) {
                    allowMethod = request.getHeader("Access-Control-Request-Method");
                    allowHeaders = request.getHeader("Access-Control-Request-Headers");
                } else {
                    allowMethod = request.getMethod();
                    ArrayList headerNames = Collections.list(request.getHeaderNames());
                    allowHeaders = StringUtils.join(headerNames, ",");
                }

                response.setHeader("Access-Control-Allow-Origin", origin);
                response.setHeader("Access-Control-Allow-Credentials", "true");
                response.setHeader("Access-Control-Allow-Methods", allowMethod);
                response.setHeader("Access-Control-Allow-Headers", allowHeaders);
                response.setHeader("Access-Control-Expose-Headers", "x-auth-token");
            }
        }
    }

    public static void addCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, String domain, String path, Integer maxAge) {
        Cookie cookie = new Cookie(cookieName, cookieValue);
        if(domain != null) {
            cookie.setDomain(domain);
        }

        if(path != null) {
            cookie.setPath(path);
        } else {
            cookie.setPath(request.getContextPath() + "/");
        }

        if(maxAge != null) {
            cookie.setMaxAge(maxAge.intValue());
        } else {
            cookie.setMaxAge(-1);
        }

        cookie.setSecure(request.isSecure());
        response.addCookie(cookie);
        logger.debug("增加cookie [" + cookieName + "] = [" + cookieValue + "]");
    }

    public static void removeCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String domain, String path) {
        Cookie cookie = new Cookie(cookieName, "");
        if(domain != null) {
            cookie.setDomain(domain);
        }

        if(path != null) {
            cookie.setPath(path);
        } else {
            cookie.setPath(request.getContextPath() + "/");
        }

        cookie.setMaxAge(0);
        response.addCookie(cookie);
        logger.debug("删除cookie [" + cookieName + "]");
    }

    public static String getRootDomain(HttpServletRequest request) {
        Pattern domainPattern = Pattern.compile("^.+?\\.(\\w+\\.[a-z]+)$", 2);
        Matcher matcher = domainPattern.matcher(request.getServerName());
        return matcher.matches()?matcher.group(1):null;
    }

    public static boolean isAPIRequest(HttpServletRequest request) {
        boolean ajax = "XMLHttpRequest".equals(request.getHeader("X-Requested-With"));
        boolean html = request.getHeader("Accept") != null && request.getHeader("Accept").contains("text/html");
        return ajax || !html;
    }

    public static void saveLastRequest(HttpServletRequest request) {
        if(request.getMethod().equalsIgnoreCase("GET") && !isAPIRequest(request)) {
            StringBuffer requestURL = request.getRequestURL();
            String query = request.getQueryString();
            if(query != null) {
                requestURL.append('?').append(query);
            }

            request.getSession().setAttribute("last_request_url", requestURL.toString());
        }

    }

    public static String getLastRequestUrl(HttpServletRequest request, boolean remove) {
        String lastRequestUrl = null;
        HttpSession session = request.getSession(false);
        if(session != null) {
            lastRequestUrl = (String)session.getAttribute("last_request_url");
            if(remove) {
                session.removeAttribute("last_request_url");
            }
        }

        return lastRequestUrl;
    }

    public static void redirectToLastRequest(HttpServletRequest request, HttpServletResponse response, String fallbackUrl) throws IOException {
        String redirecturl = getLastRequestUrl(request, true);
        if(redirecturl == null) {
            redirecturl = fallbackUrl;
        }

        if(redirecturl == null) {
            throw new IllegalStateException("最后请求地址和fallbackUrl不能同时为空");
        } else {
            response.sendRedirect(redirecturl);
        }
    }

    public static String getContextPath(HttpServletRequest request) {
        String contextPath = (String)request.getAttribute("javax.servlet.include.context_path");
        if(contextPath == null) {
            contextPath = request.getContextPath();
        }

        contextPath = normalize(contextPath, true);
        if("/".equals(contextPath)) {
            contextPath = "";
        }

        return contextPath;
    }

    public static String getRequestUri(HttpServletRequest request) {
        String uri = (String)request.getAttribute("javax.servlet.include.request_uri");
        if(uri == null) {
            uri = request.getRequestURI();
        }

        int semicolonIndex = uri.indexOf(59);
        uri = semicolonIndex != -1?uri.substring(0, semicolonIndex):uri;
        return normalize(uri, true);
    }

    private static String normalize(String path, boolean replaceBackSlash) {
        if(path == null) {
            return null;
        } else {
            String normalized = path;
            if(replaceBackSlash && path.indexOf(92) >= 0) {
                normalized = path.replace('\\', '/');
            }

            if(normalized.equals("/.")) {
                return "/";
            } else {
                if(!normalized.startsWith("/")) {
                    normalized = "/" + normalized;
                }

                while(true) {
                    int index = normalized.indexOf("//");
                    if(index < 0) {
                        while(true) {
                            index = normalized.indexOf("/./");
                            if(index < 0) {
                                while(true) {
                                    index = normalized.indexOf("/../");
                                    if(index < 0) {
                                        return normalized;
                                    }

                                    if(index == 0) {
                                        return null;
                                    }

                                    int index2 = normalized.lastIndexOf(47, index - 1);
                                    normalized = normalized.substring(0, index2) + normalized.substring(index + 3);
                                }
                            }

                            normalized = normalized.substring(0, index) + normalized.substring(index + 2);
                        }
                    }

                    normalized = normalized.substring(0, index) + normalized.substring(index + 1);
                }
            }
        }
    }

    public static String cleanQueryStringParameter(HttpServletRequest request, String cleanParameter) {
        StringBuffer buffer = request.getRequestURL();
        if(request.getQueryString() != null) {
            String queryString = request.getQueryString().replaceFirst("(&)?" + cleanParameter + "=[^&]+", "");
            if(queryString.length() > 0) {
                buffer.append("?").append(queryString);
            }
        }

        return buffer.toString();
    }
}
